package ro.peoplecentric.ctc.faces.i18n;

import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

/**
 * This class is used to publish messagesKeys in current <b>FacesContext</b> <br>
 * To benefit for the power of this class:<br>
 * In the client side it's required to have something like this:
 *
 * <pre>
 * [a4j:form]
 * 	[div]
 * 		[h:messages globalOnly="true" errorClass="Form_Message_Err" infoClass="Form_Message_Valid"/]
 * 	[/div]
 *
 * 	[a4j:commandButton  value="..." action="..." /]
 * [/a4j:form]
 * </pre>
 *
 * @author pguzun
 */
@Controller
@Scope("singleton")
public class JsfMessagePublisher {

    private static final String RESOURCE_NAME = "msgs";

    public JsfMessagePublisher() {
    }

    @SuppressWarnings("unused")
    @PostConstruct
    private void init() {
    }

    /**
     * Used to add <b>info</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param summaryKey - localized message key
     */
    public void addInfoMessage(String summaryKey) {
        addInfoMessage(null, summaryKey);
    }

    /**
     * Used to add <b>error</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param summaryKey - localized message key
     */
    public void addErrorMessage(String summaryKey) {
        addErrorMessage(null, summaryKey);
    }

    public void addErrorMessage(String summaryKey, Object[] args) {
        addErrorMessage(null, summaryKey, args);
    }

    /**
     * Used to add <b>info</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param clientId - component ID
     * @param summaryKey - localized message key
     */
    public void addInfoMessage(String clientId, String summaryKey) {
        addMessageToFacesContext(clientId, summaryKey, FacesMessage.SEVERITY_INFO);
    }

    public void addInfoMessage(String clientId, String summaryKey, Object[] args) {
        addMessageToFacesContext(clientId, summaryKey, FacesMessage.SEVERITY_INFO, args);
    }

    public void addInfoMessage(String summaryKey, Object[] args) {
        addMessageToFacesContext(null, summaryKey, FacesMessage.SEVERITY_INFO, args);
    }

    /**
     * Used to add <b>error</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param clientId - component ID
     * @param summaryKey - localized message key
     */
    public void addErrorMessage(String clientId, String summaryKey) {
        addMessageToFacesContext(clientId, summaryKey, FacesMessage.SEVERITY_ERROR);
    }

    public void addErrorMessage(String clientId, String summaryKey, Object[] args) {
        addMessageToFacesContext(clientId, summaryKey, FacesMessage.SEVERITY_ERROR, args);
    }

    /**
     * Used to add <b>warning</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param summaryKey - localized message key
     */
    public void addWarningMessage(String summaryKey) {
        addMessageToFacesContext(null, summaryKey, FacesMessage.SEVERITY_WARN);
    }

    /**
     * Used to add <b>warning</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param clientId - component ID
     * @param summaryKey - localized message key
     */
    public void addWarningMessage(String clientId, String summaryKey) {
        addMessageToFacesContext(clientId, summaryKey, FacesMessage.SEVERITY_WARN);
    }

    /**
     * Used to add <b>warning</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param clientId - component ID
     * @param summaryKey - localized message key
     * @param args - the localized message key arguments
     */
    public void addWarningMessage(String clientId, String summaryKey, Object[] args) {
        addMessageToFacesContext(clientId, summaryKey, FacesMessage.SEVERITY_WARN, args);
    }

    /**
     * Used to add <b>warning</b> message to user interface,<br>
     * this method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>.
     *
     * @param summaryKey - localized message key
     * @param args - the localized message key arguments
     */
    public void addWarningMessage(String summaryKey, Object[] args) {
        addMessageToFacesContext(null, summaryKey, FacesMessage.SEVERITY_WARN, args);
    }

    /**
     * This method creates a <b>FacesMessage</b> and add it to<br>
     * current <b>FacesContext</b>, used for user interface messages.
     *
     * @param clientId - component ID
     * @param summaryKey - Localized message key
     * @param severity - the severity (ex: SEVERITY_INFO, SEVERITY_ERROR)
     */
    private void addMessageToFacesContext(String clientId, String summaryKey, Severity severity, Object... args) {
        FacesContext fContext = FacesContext.getCurrentInstance();

        ResourceBundle resourceBundle = fContext.getApplication().getResourceBundle(fContext, RESOURCE_NAME);
        try {
            final String summaryMessage = resourceBundle.getString(summaryKey);
            fContext.addMessage(clientId, new FacesMessage(severity, MessageFormat.format(summaryMessage, args), null));
        } catch (MissingResourceException ex) {
            fContext.addMessage(clientId, new FacesMessage(severity, summaryKey, null));
        }
    }
}
